#!/usr/bin/env python
#
'''
Created on 2009-3-16

@author: Wang_Yuan
'''

import random
import wx
import wx.wizard as wiz
import core
import os
import os.path
try:
    import cPickle as pickle
except:
    import pickle

from ManagementDialog import *
from MainFrame_xrc import *

import ExamCommon
import ExamReportDialog
import PrintDialog

class MainFrame(xrcMainFrame):
    '''
    The Main Frame
    '''
    
    INFORMATION_PATTERN = """==========================
File Name: 
    %s
Word Count: %d
==========================
"""

    SETTING_FILE = os.path.realpath(os.path.expanduser('~/.IntelligentVocabulary'))

    def __init__(self, parent=None):
        '''
        Constructor
        '''
        
        xrcMainFrame.__init__(self, parent)
        self.vocabulary = core.Vocabulary()
        self.recentEventHandlers = dict()
        
        self.loadSetting()
        if self.recent:
            self.loadFile(self.recent[0])
        else:
            self.OnMenu_newFile(None)
            
        self.Bind(wiz.EVT_WIZARD_PAGE_CHANGING, self.OnWizardChanging)
        self.Bind(wiz.EVT_WIZARD_PAGE_CHANGED, self.OnWizardChanged)

    
    def OnWizardChanging(self, evt):
        print 'wizard changing'
        page = evt.GetPage()
        if hasattr(page, 'panel'):
            panel = page.panel
            if hasattr(panel, 'OnChanging'):
                panel.OnChanging(evt)

    def OnWizardChanged(self, evt):
        print 'wizard changed'
        page = evt.GetPage()
        if hasattr(page, 'panel'):
            panel = page.panel
            if hasattr(panel, 'OnChanged'):
                panel.OnChanged(evt)

    def OnMenu_newFile(self, evt):
        self.vocabulary.clear()
        self.updateVocabularyInformation()
        
    def OnMenu_openFile(self, evt):
        wildcard = \
            'Vocabulary File (*.ivo)|*.ivo|' \
            'Xml File (*.xml)|*.xml' 
        if self.recent:
            defaultDir = os.path.dirname(self.recent[0])
            defaultFile = os.path.basename(self.recent[0])
        else:
            defaultDir = os.getcwd()
            defaultFile = ''
            
        dialog = wx.FileDialog(self, 
                               message='Choose a vocabulary file', 
                               defaultDir=defaultDir, 
                               defaultFile=defaultFile, 
                               wildcard=wildcard, 
                               style=wx.OPEN | wx.CHANGE_DIR
                               )
        
        if dialog.ShowModal() == wx.ID_OK:
            self.loadFile(dialog.GetPath())
            
        dialog.Destroy()
        
    def loadSetting(self):
        '''
        Load settings from SETTING_FILE. 
        Settings include the information of recent opened file only. 
        '''
        self.recent = core.settings.getRecentList()
#        if os.path.exists(self.SETTING_FILE):
#            f = file(self.SETTING_FILE, 'r')
#            self.recent = pickle.load(f)
#            f.close()
#        else: 
#            self.recent = []
        self.updateRecentMenu()
            
    def updateRecentMenu(self):
        '''
        Update the menu items of recent file menu. 
        '''
        recentMenu = self.openRecent
        for item in recentMenu.GetMenuItems():
            recentMenu.DeleteItem(item)
        for name in self.recent:
            item = self.openRecent.Append(wx.ID_ANY, text=name)
            self.Bind(wx.EVT_MENU, self.generateOnMenu_openRecent(name), item)
            
    def saveSetting(self):
        '''
        Save information into SETTING_FILE. 
        Information includes recent opened file. 
        '''
        self.updateRecentMenu()
        core.settings.saveRecentList(self.recent)
#        f = file(self.SETTING_FILE, 'w')
#        pickle.dump(self.recent, f)
        
    def loadFile(self, fileName):
        '''
        Load vocabulary from a file. 
        @param fileName: The file name of the vocabulary file. A vocabulary file is an xml-format file. 
        '''
        self.vocabulary.clear()
        self.vocabulary.fileName = fileName
        self.vocabulary.load()
        self.updateVocabularyInformation()
        try:
            self.recent.remove(fileName)
        except:
            pass
        self.recent.insert(0, fileName)
        self.saveSetting()
        
    def updateVocabularyInformation(self):
        '''
        Update vocabulary information text box. 
        '''
        information = self.INFORMATION_PATTERN % (self.vocabulary.fileName, len(self.vocabulary.words))
        self.vocabularyInformation.SetValue(information)
        self.startExam.Enable(bool(self.vocabulary.words))
        self.mainToolBar.EnableTool(self.startExam.GetId(), bool(self.vocabulary.words))
        
    def generateOnMenu_openRecent(self, fileName):
        '''
        This function returns an openRecent menu item event handler function. 
        @param fileName: The fileName of the recent opened file. 
        '''
        handler = self.recentEventHandlers.get(fileName)
        if not handler: 
            def func(evt):
                self.loadFile(fileName)
            self.recentEventHandlers[fileName] = func
            handler = func
        return handler
    
    def OnMenu_exit(self, evt):
        self.Close()
        
    def OnMenu_manageVocabulary(self, evt):
        self.manageVocabulary(evt)
        
    def OnMenu_startExam(self, evt):
        self.startExamFunc(evt)
        
    def OnMenu_clearAllRecords(self, evt):
        self.clearAllRecords()
        
    def OnButton_manageVocabulary(self, evt):
        self.manageVocabulary(evt)
        
    def OnButton_startExam(self, evt):
        self.startExamFunc(evt)
        
    def OnMenu_print(self, evt):
        print 'print...'
        dialog = PrintDialog.PrintDialog(self, self.vocabulary)
        dialog.CenterOnParent()
        dialog.ShowModal()
        dialog.Destroy()
        
    def OnClose(self, evt):
        core.sound.terminate()
        evt.Skip()
        
    def clearAllRecords(self):
        if wx.MessageBox('This will clear all the exam records of this vocabulary. \nContinue?', 
                         caption='confirm',
                         style=wx.YES_NO|wx.ICON_QUESTION) == wx.YES:
            self.vocabulary.clearAllRecords()
            self.vocabulary.save()
        
    def manageVocabulary(self, evt):
        print 'manage vocabulary'
        dialog = ManagementDialog(self, wx.ID_ANY, 'Vocabulary Manager')
        def showDialog():
            dialog.ShowModal()
            dialog.Destroy()
            self.updateVocabularyInformation()
        wx.CallAfter(showDialog)
    
    def startExamFunc(self, evt):
        print 'start exam'
        def startExam():
#            wizard = wiz.Wizard(self, wx.ID_ANY, 'Exam', style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX)
#            settingsPage = ExamCommon.ExamSettingsWizardPage(wizard, self.vocabulary)
#            # wizard.GetPageAreaSizer().Add(settingsPage)
#            # wizard.GetPageAreaSizer().SetMinSize((400, 300))
#            wizard.RunWizard(settingsPage)
            originalQuestionList = self.getQuestionList()
            print originalQuestionList
            if originalQuestionList:
                self.loopExam(originalQuestionList)
                dialog = ExamReportDialog.ExamReportDialog(self, originalQuestionList)
                dialog.ShowModal()
                dialog.Destroy()
                self.vocabulary.save()
            
        wx.CallAfter(startExam)
        
    def getQuestionList(self):
        '''
        Popup a setup wizard and return a question list. 
        @return: list,  a question list, the first element, qList[0], is a list that use to store error questions. 
        '''
        ret = None
        wizard = wiz.Wizard(self, wx.ID_ANY, 'Exam Settings', style=wx.DEFAULT_DIALOG_STYLE, bitmap=ExamCommon.getSettingBitmap())
        settingsPage = ExamCommon.ExamSettingsWizardPage(wizard, self.vocabulary)
        if wizard.RunWizard(settingsPage):
            settingsPanel = settingsPage.panel
            settings = settingsPanel.getSettings()
            qTypeIndexes = settings.getQTypeIndexes()
            qAmount = settings.getQAmount()
            examWordList = self.vocabulary.getExamWordList(settingsPanel.examWordList, qAmount)
            random.shuffle(examWordList)
            questionList = map(lambda data: ExamCommon.ExamQuestion(self.vocabulary, data, qTypeIndexes), 
                               examWordList)
            questionList.insert(0, [])
            ret = questionList
        wizard.Destroy()
        return ret
        
    def runExam(self, questionList):
        '''
        Run single exam once. 
        '''
        ret = None
        flag = False
        for index, question in zip(xrange(1,len(questionList)), questionList[1:]):
            if question.validated:
                flag = True
                break
        if flag:
            wizard = wiz.Wizard(self, wx.ID_ANY, 'Exam Settings', style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER|wx.MAXIMIZE_BOX|wx.MINIMIZE_BOX, bitmap=ExamCommon.getQuestionBitmap())
            questionPage = ExamCommon.QuestionWizardPage(wizard, index, questionList)
            if wizard.RunWizard(questionPage):
                newList = list(questionList[0])
                random.shuffle(newList)
                newList.insert(0, [])
                ret = newList
            else:
                ret = None
            wizard.Destroy()
        else:
            ret = None
        
        return ret
    
    def loopExam(self, questionList):
        '''
        Run exams until no error or cancel. 
        '''
        while questionList and len(questionList) > 1:
            questionList = self.runExam(questionList)
            if questionList and len(questionList) > 1:
                if wx.MessageBox(
                              'There is %s words still need exam. \nContinue?' % (len(questionList) - 1,), 
                              caption='Confirm', 
                              style=wx.YES_NO|wx.ICON_QUESTION,
                              ) == wx.NO:
                    break

        
if __name__ == '__main__':
    app = wx.App(0)
    frame = MainFrame(None)
    app.SetTopWindow(frame)
    frame.Show()
    app.MainLoop()
    